package edu.washington.ling.syntric.consistency;

import java.util.LinkedList;
import java.util.List;

import edu.washington.ling.syntric.struct.tree.Token;
import edu.washington.ling.syntric.struct.tree.Tree;

public class CausativeRule extends ConsistencyRule {

	@Override
	public void apply(Tree ds) {
		Token dsRoot = ds.getDSRoot();
		apply(dsRoot, ds);
	}

	public void apply(Token t, Tree ds) {
		Token pk1Child = null;
		// TODO: This is a compromise 
		//       Need to determine the entire class of elements that should attach 
		//       to the CAUS node
		List<Token> advChildren = new LinkedList<Token>();
		for (Token child: t.getDSDependents()) {
			if (child.getDSRelation().equals("pk1")) {
				pk1Child = child;
			}
			if (child.getDSRelation().matches("(k7.*|adv|vmod.*)")) {
				advChildren.add(child);
			}
		}
		// Diagnostic test
		// TODO: This is a compromise and it overgenerates. 
		//       We will eventually have a feature that will identify indirect
		//       causatives.
		if (t.getTag().equals("VM") && (pk1Child != null)) {
			
			// Operation					
			
			// Create an IMPARG EC and attach it to the verb with k1 relation
			Token impargEC = ConsistencyUtils.createBaseEC("IMPARG", "k1");
			// Attach ec as a child of the verb
			t.addECDependent(impargEC);
			
			// Create a CAUS EC and attach it to the verb's parent (if it has one),
			// or as the root. Attach the verb as a child of the new CAUS EC
			Token causEC = ConsistencyUtils.createBaseEC("CAUS", t.getDSRelation());
			Token parent = t.getDSHead();
			if (parent != null)  {
				parent.addDSDependent(causEC);
				causEC.setDSHead(parent);
			} else {
				ds.setDSRoot(causEC);
			}
			t.setDSRelation("k2");
			causEC.addDSDependent(t);
			t.setDSHead(causEC);
			OrderUtils.insertRightOfToken(causEC, t, ds);
			// If pk1 child exists, remove it as child of verb and attach it to the 
			// newly created CAUS EC
			if (pk1Child != null) {
				t.removeDSDependent(pk1Child);
				causEC.addDSDependent(pk1Child);
				pk1Child.setDSHead(causEC);
			}
			// If adv children exist, remove them as child of verb and attach them
			// to the newly created CAUS EC
			if (advChildren.size() > 0) {
				for (Token advChild: advChildren) {
					t.removeDSDependent(advChild);
					causEC.addDSDependent(advChild);
					advChild.setDSHead(causEC);
				}
			}
			
		}
		// This rule adds an EC in between the triggering node and its 
		// parent, so will change that parent's list of children. therefore
		// when applying to children it must apply to a copy of the list
		List<Token> copyOfChildren = new LinkedList<Token>(t.getDSDependents());
		for (Token child: copyOfChildren) {
			apply(child, ds);
		}
	}
	

}
